﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.IO;
using USB2XXX;
//若运行程序提示无法加载或者找不到USB2XXX.dll文件，将工程目录下的USB2XXX.dll和libusb-1.0.dll文件拷贝到exe程序输出目录下即可
namespace USB2XXX_CANFD_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            USB_DEVICE.DEVICE_INFO DevInfo = new USB_DEVICE.DEVICE_INFO();
            Int32[] DevHandles = new Int32[20];
            Int32 DevHandle = 0;
            Byte SendCANIndex = 0;
            Byte ReadCANIndex = 1;
            bool state;
            Int32 DevNum, ret;
            string dllFilePath = "USB2XXX.dll";
            if (!File.Exists(dllFilePath))
            {
                Console.WriteLine("请先将USB2XXX.dll和libusb-1.0.dll文件复制到exe程序文件输出目录下!");
                Console.WriteLine("dll文件在‘usb2can_lin_pwm_example/sdk/libs/windows’目录下！");
                Console.WriteLine("程序是32位的就复制‘x86’目录下文件，程序是64位的就复制‘x86_64’目录下文件！");
                return;
            }
            USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[10240];
            for (int i = 0; i < CanMsgBuffer.Length; i++)
            {
                CanMsgBuffer[i] = new USB2CANFD.CANFD_MSG();
                CanMsgBuffer[i].Data = new Byte[64];
            }
            //扫描查找设备
            DevNum = USB_DEVICE.USB_ScanDevice(DevHandles);
            if (DevNum <= 0)
            {
                Console.WriteLine("No device connected!");
                return;
            }
            else
            {
                Console.WriteLine("Have {0} device connected!", DevNum);
            }
            DevHandle = DevHandles[0];
            //打开设备
            state = USB_DEVICE.USB_OpenDevice(DevHandle);
            if (!state)
            {
                Console.WriteLine("Open device error!");
                return;
            }
            else
            {
                Console.WriteLine("Open device success!");
            }
            //获取固件信息
            StringBuilder FuncStr = new StringBuilder(256);
            state = USB_DEVICE.DEV_GetDeviceInfo(DevHandle, ref DevInfo, FuncStr);
            if (!state)
            {
                Console.WriteLine("Get device infomation error!");
                return;
            }
            else
            {
                Console.WriteLine("Firmware Info:");
                Console.WriteLine("    Name:" + Encoding.Default.GetString(DevInfo.FirmwareName));
                Console.WriteLine("    Build Date:" + Encoding.Default.GetString(DevInfo.BuildDate));
                Console.WriteLine("    Firmware Version:v{0}.{1}.{2}", (DevInfo.FirmwareVersion >> 24) & 0xFF, (DevInfo.FirmwareVersion >> 16) & 0xFF, DevInfo.FirmwareVersion & 0xFFFF);
                Console.WriteLine("    Hardware Version:v{0}.{1}.{2}", (DevInfo.HardwareVersion >> 24) & 0xFF, (DevInfo.HardwareVersion >> 16) & 0xFF, DevInfo.HardwareVersion & 0xFFFF);
                Console.WriteLine("    Functions:" + DevInfo.Functions.ToString("X8"));
                Console.WriteLine("    Functions String:" + FuncStr);
            }
            //初始化配置CANFD设备
            USB2CANFD.CANFD_INIT_CONFIG CANFDConfig = new USB2CANFD.CANFD_INIT_CONFIG();
            //填充初始化参数
            ret = USB2CANFD.CANFD_GetCANSpeedArg(DevHandle, ref CANFDConfig,500000,2000000);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Get CANFD Speed failed!");
                return;
            }
            else
            {
                Console.WriteLine("Get CANFD Speed Success!");
            }
            CANFDConfig.ISOCRCEnable = 1;//使能ISOCRC
            ret = USB2CANFD.CANFD_Init(DevHandle, SendCANIndex, ref CANFDConfig);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Config CANFD failed!");
                return;
            }
            else
            {
                Console.WriteLine("Config CANFD Success!");
            }
            ret = USB2CANFD.CANFD_Init(DevHandle, ReadCANIndex, ref CANFDConfig);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Config CANFD failed!");
                return;
            }
            else
            {
                Console.WriteLine("Config CANFD Success!");
            }
            //配置过滤器，若不配置过滤器，默认是接收所有数据
            USB2CANFD.CANFD_FILTER_CONFIG CANFDFilter = new USB2CANFD.CANFD_FILTER_CONFIG();
            CANFDFilter.Index = 0;//取值范围为：0~31
            CANFDFilter.Enable = 1;//0-禁止过滤器，也就是不接收数据
            //配置为接收所有数据
            CANFDFilter.ID_Accept = 0x00000000;
            CANFDFilter.ID_Mask = 0x00000000;//若需要接收指定ID数据，可以将该值设置为0xFFFFFFFF，同时把ID_Accept设置为需要接收的ID值，若该ID为扩展帧ID，ID_Accept还需要按位或上0x80000000
            ret = USB2CANFD.CANFD_SetFilter(DevHandle, ReadCANIndex, ref CANFDFilter, 1);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Config filter failed!");
                return;
            }
            else
            {
                Console.WriteLine("Config filter success!");
            }
            //清空缓冲区数据
            ret = USB2CANFD.CANFD_ClearMsg(DevHandle, ReadCANIndex);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Clear Message Failed!");
                return;
            }
            else
            {
                Console.WriteLine("Clear Message Success!");
            }
            //启动CAN数据接收
            ret = USB2CANFD.CANFD_StartGetMsg(DevHandle, ReadCANIndex);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Start receive CANFD failed!");
                return;
            }
            else
            {
                Console.WriteLine("Start receive CANFD Success!");
            }
            //发送CAN数据
            USB2CANFD.CANFD_MSG[] CanMsg = new USB2CANFD.CANFD_MSG[5];
            IntPtr pCanSendMsg = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsg.Length);//申请缓冲区
            for (Int32 i = 0; i < 5; i++)
            {
                Int32 id = i;
                CanMsg[i] = new USB2CANFD.CANFD_MSG();
                //bit[0]-BRS,bit[1]-ESI,bit[2]-FDF,bit[6..5]-Channel,bit[7]-RXD
                CanMsg[i].Flags |= USB2CANFD.CANFD_MSG_FLAG_FDF;//按位或上CANFD_MSG_FLAG_FDF是设置为CANFD帧，按位或上CANFD_MSG_FLAG_FDF|CANFD_MSG_FLAG_BRS是设置为CANFD加速
                CanMsg[i].DLC = 8;
                CanMsg[i].ID = (UInt32)(id | USB2CANFD.CANFD_MSG_FLAG_IDE);//按位或上CANFD_MSG_FLAG_IDE是设置ID为扩展帧ID
                CanMsg[i].Data = new Byte[64];
                for (int j = 0; j < CanMsg[i].DLC; j++)
                {
                    CanMsg[i].Data[j] = (Byte)j;
                }
                //将数组中的数据复制到数据缓冲区中
                IntPtr pPonitor = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
                Marshal.StructureToPtr(CanMsg[i], pPonitor, true);
                byte[] buffer = new byte[Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))];
                Marshal.Copy(pPonitor, buffer, 0, Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
                Marshal.Copy(buffer, 0, (IntPtr)(pCanSendMsg + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
                Marshal.FreeHGlobal(pPonitor);//释放缓冲区
            }
            int SendedMsgNum = USB2CANFD.CANFD_SendMsg(DevHandle, SendCANIndex, pCanSendMsg, CanMsg.Length);
            if (SendedMsgNum >= 0)
            {
                Console.WriteLine("Success send frames:{0}", SendedMsgNum);
                for (int i = 0; i < SendedMsgNum; i++)
                {
                    CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(pCanSendMsg + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
                    Console.WriteLine("TxCanMsg[{0}].ID = 0x{1:X8}", i, CanMsgBuffer[i].ID & USB2CANFD.CANFD_MSG_FLAG_ID_MASK);
                    Int64 tus = ((((Int64)CanMsgBuffer[i].TimeStampHigh << 32) | CanMsgBuffer[i].TimeStamp) * 10);
                    Console.WriteLine("TxCanMsg[{0}].TimeStamp = {1}", i, tus / 1000000.0);//时间戳按照秒来显示
                    Console.Write("TxCanMsg[{0}].Data = ", i);
                    for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
                    {
                        Console.Write("{0:X2} ", CanMsgBuffer[i].Data[j]);
                    }
                    Console.WriteLine("\n");
                }
            }
            else
            {
                Console.WriteLine("Send CAN data failed!");
            }
            Console.WriteLine("--------------------------------------------------------------");
            //延时
            System.Threading.Thread.Sleep(100);
            //读取接收数据缓冲中的数据
            //将缓冲区转换成指针
            IntPtr pCanGetMsg = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);//申请缓冲区
            for (int t = 0; t < 100; t++)
            {
                int GetMsgNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, pCanGetMsg, CanMsgBuffer.Length);
                if (GetMsgNum > 0)
                {
                    for (int i = 0; i < GetMsgNum; i++)
                    {
                        CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(pCanGetMsg + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
                        Console.WriteLine("RxCanMsg[{0}].ID = 0x{1:X8}", i, CanMsgBuffer[i].ID & USB2CANFD.CANFD_MSG_FLAG_ID_MASK);
                        Int64 tus = ((((Int64)CanMsgBuffer[i].TimeStampHigh << 32) | CanMsgBuffer[i].TimeStamp) * 10);
                        Console.WriteLine("RxCanMsg[{0}].TimeStamp = {1}", i, tus/1000000.0);//时间戳按照秒来显示
                        for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
                        {
                            Console.Write("{0:X2} ", CanMsgBuffer[i].Data[j]);
                        }
                        Console.WriteLine("\n");
                    }
                }
                else if (GetMsgNum < 0)
                {
                    Console.WriteLine("Get CAN data error!");
                }
                System.Threading.Thread.Sleep(10);
            }
            Marshal.FreeHGlobal(pCanGetMsg);//释放缓冲区
            //停止接收数据
            ret = USB2CANFD.CANFD_StopGetMsg(DevHandle, ReadCANIndex);
            if (ret != USB2CANFD.CANFD_SUCCESS)
            {
                Console.WriteLine("Stop receive CANFD failed!");
                return;
            }
            else
            {
                Console.WriteLine("Stop receive CANFD Success!");
            }
            Console.ReadLine();
        }
    }
}
